/**
 * 显示二次扫码信息
 * 具体逻辑见 services/qywxs/index.ts 里的 initListenRescan()
 */
import { CloseCircleFilled } from '@ant-design/icons'
import { zfill } from '@gnlab/utils'
import { Badge, Tag, Result } from 'antd'
import classNames from 'classnames'
import dayjs from 'dayjs'
import { OrderedSet, type OrderedMap } from 'immutable'
import { ImportantEditModal } from '@/desktop/components'
import { useRescanQywxs, type RescanStatusInfo } from '@/desktop/logics/qywx/notify'
import { ellipsis, colors, lightBorder } from '@/desktop/styles'

export function RescanModal() {
  const { infoMap, remove } = useRescanQywxs()
  const { hasInfoToShow, closeModal } = useCloseModal(infoMap, remove)

  // 指定当前要查看的企微
  const [rawCurrent, setRawCurrent] = useState<string | null>(null)
  const current = (rawCurrent !== null ? infoMap.get(rawCurrent) : null) ?? infoMap.first() ?? null

  const [now, setNow] = useState(dayjs())
  useEffect(() => {
    const intervalId = setInterval(() => setNow(dayjs()), 1000)
    return () => clearInterval(intervalId)
  }, [])
  const countdown = current ? Math.round(current.limit.diff(now) / 1000) : 0
  const countdownMinutes = zfill(Math.floor(countdown / 60))
  const countdownSeconds = zfill(countdown % 60)

  if (!current) return
  return <ImportantEditModal
    css={s.modal}
    open={!!hasInfoToShow}
    onCancel={closeModal}
    title="企微安全验证"
    width={900}
  >
    <main css={s.layout}>
      <aside css={s.qywxs}>
        <h2>企业微信</h2>
        {[...infoMap.reverse().values()].map(info => <Badge
          css={s.qywxWrap}
          key={info.wxid}
          count={<CloseCircleFilled className="remove" onClick={() => remove([info.wxid])} />}
          offset={[-1, 1]}
        >
          <div
            css={s.qywx}
            className={classNames(
              current.wxid === info.wxid && 'current',
              !info.scanned && info.limit.isBefore() && 'invalid',
            )}
            onClick={() => setRawCurrent(info.wxid)}
          >
            <img src={info.avatar} />
            <span className="name">{info.name}</span>
            {info.scanned ? <Tag color="success">已扫码</Tag> : null}
            {!info.scanned && info.limit.isBefore() ? <Tag>已过期</Tag> : null}
          </div>
        </Badge>)}
      </aside>

      <div css={s.info}>
        <h3>你正在一台新设备上使用企业微信，需通过手机企业微信扫码进行安全验证</h3>
        {!current.scanned && !current.limit.isBefore() ? (
          <>
            <div css={s.countdown}>
              <span>
                {countdownMinutes}:{countdownSeconds}
              </span>
              内未完成安全验证，将自动退出登录
            </div>
            <div css={s.qrcode}>
              <img src={current.qrcode} />
            </div>
          </>
        ) : current.scanned ? (
          <Result status="success" title="已扫码" subTitle="等待企微通过验证" />
        ) : (
          <Result status="warning" title="已过期" subTitle="未能按时扫码通过验证" />
        )}
      </div>
    </main>
  </ImportantEditModal>
}

/**
 * 处理“关闭对话框”的逻辑
 * 1. 关闭对话框时，把当前企微都加入“忽略列表”，只有出现不在列表里的新企微时，才重新显示对话框；列表里的企微状态变化不会导致对话框重新出现。
 * 2. 关闭对话框时，把“已过期”不能再扫码的企微从记录里完全移除。
 */
function useCloseModal(
  infoMap: OrderedMap<string, RescanStatusInfo>,
  remove: (wxids: string[]) => void,
) {
  // 忽略的企微列表（不会因这些企微出现在 infos 里而显示对话框）
  const [ignoreWxids, setIgnoreWxids] = useState(OrderedSet<string>())

  // 企微登录成功时，把它从忽略列表里移除（以保证下次触发二次扫码依然能显示出来）
  useEffect(() => {
    setIgnoreWxids(ignoreWxids => {
      infoMap
        .filter(qywx => qywx.scanned)
        .forEach(qywx => {
          ignoreWxids = ignoreWxids.delete(qywx.wxid)
        })
      return ignoreWxids
    })
  }, [infoMap])

  function closeModal() {
    const toRemove: string[] = []
    const toIgnore: string[] = []
    for (const info of infoMap.values()) {
      if (!info.scanned && info.limit.isBefore()) toRemove.push(info.wxid)
      else toIgnore.push(info.wxid)
    }
    if (toRemove.length) remove(toRemove)
    setIgnoreWxids(OrderedSet(toIgnore))
  }

  const hasInfoToShow = !!infoMap.find(qywx => !ignoreWxids.has(qywx.wxid))

  return {
    hasInfoToShow,
    closeModal,
  }
}

const s = {
  modal: css`
    .ant-modal-content {
      padding-bottom: 0;
    }
  `,
  layout: css`
    display: flex;
    margin-top: 20px;
    max-height: 50vh;
    padding-left: 0 !important;
  `,

  qywxs: css`
    border-right: ${lightBorder};
    margin-right: 20px;
    overflow-x: hidden;
    overflow-y: auto;
    padding: 0 8px 12px;
    width: 220px;
    h2 {
      color: #555;
      font-size: 12px;
      margin-bottom: 9px;
      padding-left: 8px;
    }
  `,
  qywxWrap: css`
    margin-bottom: 3px;
    width: 100%;
    .remove {
      color: ${colors.error};
      cursor: pointer;
      display: none;
    }
    &:hover > .remove {
      display: block;
    }
  `,
  qywx: css`
    align-items: center;
    border-radius: 6px;
    column-gap: 6px;
    cursor: pointer;
    display: flex;
    padding: 8px;
    transition: 0.1s all linear;
    width: 100%;

    &.current,
    &:hover {
      background-color: #e6f4ff;
      color: ${colors.highlight};
    }
    &.invalid {
      color: ${colors.gray};
    }

    img {
      border-radius: 26px;
      height: 26px;
      width: 26px;
    }
    .name {
      ${ellipsis};
      font-size: 12px;
      flex: 1;
    }

    .ant-tag {
      margin: 0;
    }
    .ant-tag.success {
      background-color: #f0f0f0;
    }
  `,

  info: css`
    text-align: center;
    flex: 1;
    padding: 6px 0 20px;
    & > h3 {
      font-size: 18px;
      margin-bottom: 6px;
    }
  `,
  countdown: css`
    color: #777;
    font-size: 16px;
    & > span {
      color: ${colors.highlight};
      display: inline-block;
      width: 3.5em;
    }
  `,
  qrcode: css`
    padding: 35px 0;
    img {
      display: block;
      height: 200px;
      margin: 0 auto;
      width: 200px;
    }
  `,
}
